package cz.possoft.client.piskvorky.gui.components;

import java.awt.Color;
import java.awt.Graphics;

import cz.possoft.client.gui.gamepanel.components.GamePane;
import cz.possoft.generic.utils.GenericUtils;
import cz.possoft.serializable.generic.HraciPole;
import cz.possoft.serializable.generic.Location;
import cz.possoft.serializable.piskvorky.game.PiskvorkyPole;

public class PiskvorkyPane extends GamePane implements Runnable {
	
	public static final int ROZMER_CTVERCE = 440 / PiskvorkyPole.POCET_CTVERCU;
	
	// misto kde se nachazi oznacena figurka prstencem.
	Location ringFigurkaLocation = new Location(-1, -1);
	
	// indikator, zda je prave vlakno spusteno. Pouzity pro mizeni i objevovani
	private boolean runFlag = false;	
	
	// vlakno patrici k tomuto chessPane
	private Thread thisThread;
	
	// count udava pocet pixelu o ktere se zvysuje pri vykresleni krizku a kolecka
	// count_uhel udava o kolik se zvysuje uhel
	// sleep_interval je interval pri padani 
	private static final int COUNT = 2;	
	//private static final int POCATEK_PADANI = 0;
	private static final int SLEEP_INTERVAL = 500; 
	
	// pomocne konstanty pri vykreslovani krizku a kolecka
	private static final int DRAW_LINE_POM = 4;
	private static final int DRAW_ARC_POM = 2;
	
	// souradnice pouzite pri kresleni krizku a kolecka. xCil a yCil jsou zaverecne.
	// xWork a yWork jsou prubezne
	private int xCil = -100;
	private int yCil = -100;	
	private int count;		
	
	// Misto, na ktere prave je vykreslovan krizek ci kolecko. Na tomto miste se nebude kreslit
	private Location dontPaintLocation = new Location(-1, -1).setNull();
	
	public PiskvorkyPane() {    	
	}
	   
    // nasetuje hraci pole a provede dalsi inicializacni akce,
    // nakresleni atd.
    public void init(HraciPole hPole) { 
    	thisThread = new Thread(this);
    	thisThread.start();
    	addMouseMotionListener(new PiskvorkyMouseMotionListener());
    	addMouseListener(new PiskvorkyMouseListener());    	
    	setHraciPole(hPole);
    }
    
    // Nakresleni sachovnice     
    public void paint(Graphics g)  {
     super.paint(g);
     g.setColor(Color.BLUE);
     g.fillRect(0,0,450,450);
     for (int i=0 ; i<PiskvorkyPole.POCET_CTVERCU ; i++)
    	 for (int j=0 ; j<PiskvorkyPole.POCET_CTVERCU ; j++) {
    		 paintFigurka(i,j,g);
    	 }            
   } 
    
    // nakresli jednu figurku (ctverecek) v hracim poli na 
    // specifikovanych souradnicich.
    private void paintFigurka(int x, int y, Graphics g) {    	
    	
    	g.setColor(Color.BLACK);    	
    	// figurky z vitezne rady obarvime svetle zelene
    	if (((PiskvorkyPole)getHraciPole()).getFigurka(x, y).isPartOfWinningLine()) {
    		g.setColor(new Color(160, 255, 160));
    	}

    	// zkousime jestli se nejedna figurku, na kterou prave pada balonek
    	boolean dontPaintFlag = false;
    	if ((dontPaintLocation.getX() == x) && (dontPaintLocation.getY() == y)) {
    	//	g.setColor(Color.BLACK);
    		dontPaintFlag = true;
    	}
    	int xx = getXForPaint(x);
    	int yy = getYForPaint(y);
    	g.fillRect(xx, yy, ROZMER_CTVERCE, ROZMER_CTVERCE);
    	if ((!dontPaintFlag) || (count%2 == 0)) {
    	    paintKrizekOrKolecko(xx, yy, ((PiskvorkyPole)getHraciPole()).getFigurka(x, y).getColor(), g);
    	}    	
    	
	    // misto oznacene pro spusteni balonku
	    if ((ringFigurkaLocation.getX() == x) && (ringFigurkaLocation.getY() == y)) {	    	
	    	g.setColor(Color.GREEN);
	    	g.drawRect(xx+1, yy+1, ROZMER_CTVERCE - 2, ROZMER_CTVERCE - 2);	    	
	    }    		    
	    g.setColor(Color.GRAY); 	    
    	g.drawRect(xx, yy, ROZMER_CTVERCE, ROZMER_CTVERCE);
    } 
    
    private void paintKrizekOrKolecko(int x, int y, int color, Graphics g) {
    	if (color == GenericUtils.COLOR_NEUTRAL) {
    		return;
    	}
    	if (color == GenericUtils.COLOR_WHITE) {
    	    g.setColor(Color.RED);	    	    
    	    g.drawArc(x+DRAW_ARC_POM, y+DRAW_ARC_POM, ROZMER_CTVERCE-DRAW_ARC_POM*2, ROZMER_CTVERCE-DRAW_ARC_POM*2, 0, 360);    	    
    	    g.drawArc(x+DRAW_ARC_POM+1, y+DRAW_ARC_POM+1, ROZMER_CTVERCE-(DRAW_ARC_POM*2)-2, ROZMER_CTVERCE-(DRAW_ARC_POM*2)-2, 0, 360);    	        	    
    	}
    	else {
    		g.setColor(Color.YELLOW);    		
    	    g.drawLine(x + DRAW_LINE_POM, y + DRAW_LINE_POM, x + ROZMER_CTVERCE - DRAW_LINE_POM, y + ROZMER_CTVERCE -DRAW_LINE_POM);
    	    g.drawLine(x + DRAW_LINE_POM, y + ROZMER_CTVERCE - DRAW_LINE_POM, x + ROZMER_CTVERCE - DRAW_LINE_POM, y + DRAW_LINE_POM);    		
    	}    	
    }    
    
	// Vraci bod, kde se zacina kreslit pro lokaci X na sachovnici.	
	private int getXForPaint(int x) {		
		return 8 + x * ROZMER_CTVERCE;		
	}

	// Vraci bod, kde se zacina kreslit pro lokaci Y na sachovnici.
	private int getYForPaint(int y) {		
		return 8 + y * ROZMER_CTVERCE;		
	}

	public Location getRingFigurkaLocation() {
		return ringFigurkaLocation;
	}

	public void setRingFigurkaLocation(Location ringFigurkaLocation) {
		this.ringFigurkaLocation = ringFigurkaLocation;
	}        
    
	// metoda run bezi stale, ale priznak runFlag je true jen pokud se prave
	// prekresluje kolecko nebo krizek
    public void run() {
		while (true) {							
			try {				
				synchronized(thisThread) {
				      thisThread.wait();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}			        
			while (runFlag) {	
										
				try {
					// sleep 15 pokud je vlakno aktivni - probiha mizeni nebo objevovani figurky	
					Thread.sleep(SLEEP_INTERVAL);
				} catch (Exception e) {
					e.printStackTrace();
				}
				if (runFlag) {
					// udava jestli jiz kresleni krizku ci kolecka skoncilo								                                       
					if (count++ > COUNT) {
						dontPaintLocation.setNull();
						count = 0;
						runFlag = false;															
					}							
					repaint();
				}						
			}
           }    	
    }
    
    // inicicializuje kroky pro odehrani tahu (postupne kresleni
    // krizku ci kolecka
    public void startMalovani(int x, int y, int color) {
		dontPaintLocation.setX(x);
		dontPaintLocation.setY(y);
		xCil = getXForPaint(x);
		yCil = getYForPaint(y);		
		count = 0;
		runFlag = true;
		synchronized(thisThread) {
		     thisThread.notify();
		}		    	
    }

}
